home *** CD-ROM | disk | FTP | other *** search
- /* jdn.c -- Julian Day Number computation
- **
- ** public domain Julian Day Number functions
- **
- ** Based on formulae originally posted by
- ** Tom Van Flandern / Washington, DC / metares@well.sf.ca.us
- ** in the UseNet newsgroup sci.astro.
- ** Reposted 14 May 1991 in FidoNet C Echo conference by
- ** Paul Schlyter (Stockholm)
- ** Minor corrections, added JDN to julian, and recast into C by
- ** Raymond Gardner Englewood, Colorado
- **
- ** Synopsis:
- ** long ymd_to_jdn(int year, int month, int day, int julian_flag)
- ** void jdn_to_ymd(long jdn, int *year, int *month, int *day,
- ** int julian_flag)
- ** year is negative if BC
- ** if julian_flag is > 0, use Julian calendar
- ** if julian_flag is == 0, use Gregorian calendar
- ** if julian_flag is < 0, routines decide based on date
- **
- ** These routines convert Gregorian and Julian calendar dates to and
- ** from Julian Day Numbers. Julian Day Numbers (JDN) are used by
- ** astronomers as a date/time measure independent of calendars and
- ** convenient for computing the elapsed time between dates. The JDN
- ** for any date/time is the number of days (including fractional
- ** days) elapsed since noon, 1 Jan 4713 BC. Julian Day Numbers were
- ** originated by Joseph Scaliger in 1582 and named after his father
- ** Julius, not after Julius Caesar. They are not related to the
- ** Julian calendar.
- **
- ** For dates from 1 Jan 4713 BC thru 12 Dec Feb 32766 AD, ymd_to_jdn()
- ** will give the JDN for noon on that date. jdn_to_ymd() will compute
- ** the year, month, and day from the JDN. Years BC are given (and
- ** returned) as negative numbers. Note that there is no year 0 BC;
- ** the day before 1 Jan 1 AD is 31 Dec 1 BC. Note also that 1 BC,
- ** 5 BC, etc. are leap years.
- **
- ** Pope Gregory XIII decreed that the Julian calendar would end on
- ** 4 Oct 1582 AD and that the next day would be 15 Oct 1582 in the
- ** Gregorian Calendar. The only other change is that centesimal
- ** years (years ending in 00) would no longer be leap years
- ** unless divisible by 400. Britain and its possessions and
- ** colonies continued to use the Julian calendar up until 2 Sep
- ** 1752, when the next day became 14 Sep 1752 in the Gregorian
- ** Calendar. These routines can be compiled to use either
- ** convention. By default, the British convention will be used.
- ** Simply #define PAPAL to use Pope Gregory's convention.
- **
- ** Each routine takes, as its last argument, a flag to indicate
- ** whether to use the Julian or Gregorian calendar convention. If
- ** this flag is negative, the routines decide based on the date
- ** itself, using the changeover date described in the preceding
- ** paragraph. If the flag is zero, Gregorian conventions will be used,
- ** and if the flag is positive, Julian conventions will be used.
- */
-
-
- #ifdef PAPAL /* Pope Gregory XIII's decree */
- #define LASTJULDATE 15821004L /* last day to use Julian calendar */
- #define LASTJULJDN 2299160L /* jdn of same */
- #else /* British-American usage */
- #define LASTJULDATE 17520902L /* last day to use Julian calendar */
- #define LASTJULJDN 2361221L /* jdn of same */
- #endif
-
-
- long ymd_to_jdn(int y, int m, int d, int julian)
- {
- long jdn;
-
- if (julian < 0) /* set Julian flag if auto set */
- julian = (((y * 100L) + m) * 100 + d <= LASTJULDATE);
-
- if (y < 0) /* adjust BC year */
- y++;
-
- if (julian)
- jdn = 367L * y - 7 * (y + 5001L + (m - 9) / 7) / 4
- + 275 * m / 9 + d + 1729777L;
- else
- jdn = (long)(d - 32076)
- + 1461L * (y + 4800L + (m - 14) / 12) / 4
- + 367 * (m - 2 - (m - 14) / 12 * 12) / 12
- - 3 * ((y + 4900L + (m - 14) / 12) / 100) / 4
- + 1; /* correction by rdg */
-
- return jdn;
- }
-
-
- void jdn_to_ymd(long jdn, int *yy, int *mm, int *dd, int julian)
- {
- long x, z, m, d, y;
- long daysPer400Years = 146097L;
- long fudgedDaysPer4000Years = 1460970L + 31;
-
- if (julian < 0) /* set Julian flag if auto set */
- julian = (jdn <= LASTJULJDN);
-
- x = jdn + 68569L;
- if ( julian )
- {
- x += 38;
- daysPer400Years = 146100L;
- fudgedDaysPer4000Years = 1461000L + 1;
- }
- z = 4 * x / daysPer400Years;
- x = x - (daysPer400Years * z + 3) / 4;
- y = 4000 * (x + 1) / fudgedDaysPer4000Years;
- x = x - 1461 * y / 4 + 31;
- m = 80 * x / 2447;
- d = x - 2447 * m / 80;
- x = m / 11;
- m = m + 2 - 12 * x;
- y = 100 * (z - 49) + y + x;
-
- *yy = y;
- *mm = m;
- *dd = d;
-
- if (*yy <= 0) /* adjust BC years */
- (*yy)--;
- }
-